#ifndef __YUECHUAN_UTIL_H__
#define __YUECHUAN_UTIL_H__

#include <stdint.h>
#include "log.h"
#include "fiber.h"
#include <iostream>
#include <sys/time.h>
#include <unistd.h>
#include <cstring>
#include <sys/stat.h>
#include <fstream>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <algorithm>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <iostream>
#include <vector>
#include <execinfo.h>
#include<sys/time.h>
#include <stdarg.h>
#include <cxxabi.h>
#include "json_util.h"
#include <yaml-cpp/yaml.h>
#include <json/json.h>

namespace yuechuan {
    /*
     * 调用系统方法，获取当前程序执行的线程id
     */
    pid_t GetThreadId();

    uint32_t GetFiberId();

    /**
      * @brief 调用栈显示
      * @param bt 调用栈数组
      * @param size 栈的层数
      * @param skip 起始层数
      */
    void Backtrace(std::vector<std::string> &bt, int size, int skip = 1);

    /**
      * @brief 将调用栈转换为string类型，方便输出
      * @param size 调用栈的层数
      * @param skip 起始层数
      * @param prefix 每个栈前面要添加的字符
      * @return
    */
    std::string BacktraceToString(int size = 64, int skip = 2, const std::string &prefix = " ");

    class FSUtil {
    public:
        static bool OpenForWrite(std::ofstream &ofs, const std::string &filename, std::ios_base::openmode mode);

        static std::string Dirname(const std::string &filename);

        static bool Mkdir(const std::string &dirname);
    };

    /**
     * @brief 获取当前的毫秒时间
     * @return uint64_t
     */
    uint64_t GetCurrentTimeMS();

    /**
     * @brief 获取当前的微秒时间
     * @return uint64_t
     */
    uint64_t GetCurrentTimeUS();


    /**
     * @brief 将字符串全部转换为大写
     * @param name 要转换的字符串
     * @return std::string 转换后的字符
     */
    std::string ToUpper(const std::string &name);

    /**
     * @brief 将字符串全部转换为小写
     * @param name 要转换的字符串
     * @return std::string 转换后的字符
     */
    std::string ToLower(const std::string &name);

    /**
     * @brief 将当前时间转换为字符串
     * @param ts time_t 时间，默认为当前时间
     * @param format std::string 转换格式 满足strftime()中format的格式
     * @return std::string
     */
    std::string Time2Str(time_t ts = time(0), const std::string &format = "%Y-%m-%d %H:%M:%S");

    /**
     * @brief 将时间字符串转换为时间
     * @param str 时间字符串
     * @param format 转换的事件格式，要满足strftime()中format格式
     * @return time_t
     */
    time_t Str2Time(const char *str, const char *format = "%Y-%m-%d %H:%M:%S");

    class StringUtil {
    public:
        static std::string Format(const char *fmt, ...);

        static std::string Formatv(const char *fmt, va_list ap);

        static std::string UrlEncode(const std::string &str, bool space_as_plus = true);

        static std::string UrlDecode(const std::string &str, bool space_as_plus = true);

        static std::string Trim(const std::string &str, const std::string &delimit = " \t\t\n");

        static std::string TrimLeft(const std::string &str, const std::string &delimit = " \t\t\n");

        static std::string TrimRight(const std::string &str, const std::string &delimit = " \t\t\n");

        static std::string WStringToString(const std::wstring &ws);

        static std::wstring StringToWString(const std::string &s);

        std::string Formatv(const char *fmt, va_list *ap);
    };

    in_addr_t GetIPv4Inet();

    pid_t GetThreadId();

    uint32_t GetFiberId();

    void Backtrace(std::vector<std::string> &bt, int size, int skip);

    std::string BacktraceToString(int size, int skip, const std::string &prefix);

    std::string _GetIPv4();

    std::string GetIPv4();

    bool YamlToJson(const YAML::Node &ynode, Json::Value &jnode);

    bool JsonToYaml(const Json::Value &jnode, YAML::Node &ynode);

    template<class T>
    void delete_array(T *v) {
        if (v) {
            delete[]v;
        }
    }

    template<class T>
    const char *TypeToName() {
        static const char *s_name = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
        return s_name;
    }

    class TypeUtil {
    public:
        static int8_t ToChar(const std::string &str);

        static int64_t Atoi(const std::string &str);

        static double Atof(const std::string &str);

        static int8_t ToChar(const char *str);

        static int64_t Atoi(const char *str);

        static double Atof(const char *str);
    };
} // namespace yuechuan
#endif